/*
 * Copyright 2020 HPB Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hpb.bc.solidity.abi;

import io.hpb.web3.abi.TypeDecoder;
import io.hpb.web3.abi.datatypes.Address;
import io.hpb.web3.abi.datatypes.generated.Uint256;
import io.hpb.web3.crypto.*;
import io.hpb.web3.rlp.RlpDecoder;
import io.hpb.web3.rlp.RlpList;
import io.hpb.web3.rlp.RlpString;
import io.hpb.web3.rlp.RlpType;
import io.hpb.web3.utils.Numeric;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.security.SignatureException;
import java.util.List;

public class DecodeUtils {


    /**
     * 通过签名后会得到一个加密后的字符串
     * 本类将分析这个字符串
     */
    public static void main(String[] args) {
		/*String signedData = "0xf8ac8201518506fc23ac00830493e094fda023cea60a9f421d74ac49f9a015880a77dd7280b844a9059cbb000000000000000000000000b5dbd2e4093a501f1d1e645f04cef5815a1581d7000000000000000000000000000000000000000000000004c53ecdc18a6000001ca03d710f3c5aabde2733938c44c0b1448f96e760c030205562f59889557397faa4a007110abbcfa343381a2f713d6339d3fa751200f82cc2f06a4d1967b4eaf61d50";
		decodeMessage(signedData);
		decodeMessageV340(signedData);*/
//        testEncode();
//        testDecode();
        parseInput();

//        decodeInput();


        // demo	http://hpbscan.org/tx/0x670bcf66900760f6a91d8291faab703e6827671551dc2f774aa19f2a08947ae0
        String msg = "0x6060604052341561000f57600080fd5b6b033b2e3c9fd0803ce8000000600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506040805190810160405280600881526020017f424253546f6b656e000000000000000000000000000000000000000000000000815250600390805190602001906100b392919061010d565b506040805190810160405280600381526020017f4242530000000000000000000000000000000000000000000000000000000000815250600490805190602001906100ff92919061010d565b5060126005819055506101b2565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061014e57805160ff191683800117855561017c565b8280016001018555821561017c579182015b8281111561017b578251825591602001919060010190610160565b5b509050610189919061018d565b5090565b6101af91905b808211156101ab576000816000905550600101610193565b5090565b90565b610d42806101c16000396000f300606060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461009e578063095ea7b31461012c57806318160ddd1461018657806323b872dd146101af578063313ce5671461022857806370a082311461025157806395d89b411461029e578063a9059cbb1461032c578063dd62ed3e14610386575b600080fd5b34156100a957600080fd5b6100b16103f2565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f15780820151818401526020810190506100d6565b50505050905090810190601f16801561011e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013757600080fd5b61016c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610490565b604051808215151515815260200191505060405180910390f35b341561019157600080fd5b610199610582565b6040518082815260200191505060405180910390f35b34156101ba57600080fd5b61020e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610588565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610947565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b610288600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061094d565b6040518082815260200191505060405180910390f35b34156102a957600080fd5b6102b1610996565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102f15780820151818401526020810190506102d6565b50505050905090810190601f16801561031e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561033757600080fd5b61036c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a34565b604051808215151515815260200191505060405180910390f35b341561039157600080fd5b6103dc600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c58565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104885780601f1061045d57610100808354040283529160200191610488565b820191906000526020600020905b81548152906001019060200180831161046b57829003601f168201915b505050505081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515156105c557600080fd5b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561061357600080fd5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561069e57600080fd5b6106f082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610cdf90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061078582600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610cf890919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061085782600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610cdf90919063ffffffff16565b600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b60055481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60048054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a2c5780601f10610a0157610100808354040283529160200191610a2c565b820191906000526020600020905b815481529060010190602001808311610a0f57829003601f168201915b505050505081565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610a7157600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610abf57600080fd5b610b1182600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610cdf90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610ba682600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610cf890919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000828211151515610ced57fe5b818303905092915050565b6000808284019050838110151515610d0c57fe5b80915050929150505600a165627a7a72305820f6a0a43c737aa4c8c396ffc127d8ca9ce74b3a0c5c547eb70e1ba7ebc18fa2750029";
        // http://hpbscan.org/tx/0x1baecb8a7a9ebac26639d9027e75a98ba65fbf52c5affc800a965dba2f53afd2
        msg = "0xa9059cbb000000000000000000000000db4d90c1fe9f840eabbd0a7fba0b0f72933017250000000000000000000000000000000000000000000000000000000000000001";
        msg = "0x0000000000000000000000000000000000000000000000000000000000000001";
//		decodeMessageV340(msg);
//		decodeMessage(msg);
//		decodeMessage("0x6060604052341561000f57600080fd5b6102458061001e6000396000f3006060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318160ddd811461005b57806370a0823114610080578063a9059cbb1461009f575b600080fd5b341561006657600080fd5b61006e6100d5565b60405190815260200160405180910390f35b341561008b57600080fd5b61006e600160a060020a03600435166100db565b34156100aa57600080fd5b6100c1600160a060020a03600435166024356100f6565b604051901515815260200160405180910390f35b60005481565b600160a060020a031660009081526001602052604090205490565b6000600160a060020a038316151561010d57600080fd5b600160a060020a03331660009081526001602052604090205482111561013257600080fd5b600160a060020a03331660009081526001602052604090205461015b908363ffffffff6101f116565b600160a060020a033381166000908152600160205260408082209390935590851681522054610190908363ffffffff61020316565b600160a060020a0380851660008181526001602052604090819020939093559133909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600192915050565b6000828211156101fd57fe5b50900390565b60008282018381101561021257fe5b93925050505600a165627a7a723058204ebc2682701d501c249fc46963dab35c5bc06e94d82dad680d3ed62f120e39850029");
//		testDecode();

//        testTopic();
    }

    public static void testEncode() {


        String fun = "Transfer(address,address,uint256)";
        // ventPurchased (address , uint256)
        fun = "EventPurchased(address,uint256)";
        byte[] input = fun.getBytes();
        byte[] hash = Hash.sha3(input);
        System.out.println("Numeric.toHexString(hash); = [" + Numeric.toHexString(hash) + "]");
    }

    public static void testDecode() {
        String s = "0xc2340a9e7402ea94935d3768cd4c2307821066405d8100568bf2dad32cc36131";
        s = "0x333122b2d8a4b6fe8d0e6b7c66126584ae7a620a5be7ce7a8ac3d4ba635c63d8";
//		Numeric.
        String result = Hash.sha3String(s);
        System.out.println("result ===" + result);
        try {
            byte[] bytes = Hex.decodeHex(s);
            System.out.println(new String(bytes, "UTF-8"));
        } catch (DecoderException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    private static void decodeMessage(String signedData) {
        //样例 https://ropsten.etherscan.io/tx/0xfd8acd10d72127f29f0a01d8bcaf0165665b5598781fe01ca4bceaa6ab9f2cb0
        try {
            System.out.println(signedData);
            System.out.println("解密 newCountDownLatch " + System.currentTimeMillis());
            RlpList rlpList = RlpDecoder.decode(Numeric.hexStringToByteArray(signedData));
            List<RlpType> values = ((RlpList) rlpList.getValues().get(0)).getValues();
            BigInteger nonce = Numeric.toBigInt(((RlpString) values.get(0)).getBytes());
            BigInteger gasPrice = Numeric.toBigInt(((RlpString) values.get(1)).getBytes());
            BigInteger gasLimit = Numeric.toBigInt(((RlpString) values.get(2)).getBytes());
            String to = Numeric.toHexString(((RlpString) values.get(3)).getBytes());
            BigInteger value = Numeric.toBigInt(((RlpString) values.get(4)).getBytes());
            String data = Numeric.toHexString(((RlpString) values.get(5)).getBytes());
            RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, to, value, data);
            RlpString v = (RlpString) values.get(6);
            RlpString r = (RlpString) values.get(7);
            RlpString s = (RlpString) values.get(8);
            Sign.SignatureData signatureData = new Sign.SignatureData(
                    v.getBytes()[0],
                    Numeric.toBytesPadded(Numeric.toBigInt(r.getBytes()), 32),
                    Numeric.toBytesPadded(Numeric.toBigInt(s.getBytes()), 32));
            BigInteger pubKey = Sign.signedMessageToKey(TransactionEncoder.encode(rawTransaction), signatureData);
            System.out.println("publicKey " + pubKey.toString(16));
            String address = Numeric.prependHexPrefix(Keys.getAddress(pubKey));
            System.out.println("address " + address);
            System.out.println("解密 end " + System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 可以看到交易数据本身是没有加密的，是可以直接获取到。
     * v r s是用私钥加密的数据，利用v r s加上交易数据可以得到私钥对应的公钥及地址。
     * 所以RawTransaction里是没有fromAddress的参数的。
     * 解密出的地址就是发出交易的地址。这样一来完成了验证。
     */
    private static void decodeMessageV340(String signedData) {
        System.out.println("解密 newCountDownLatch " + System.currentTimeMillis());
        RawTransaction rawTransaction = TransactionDecoder.decode(signedData);
        if (rawTransaction instanceof SignedRawTransaction) {
            try {
                String from = ((SignedRawTransaction) rawTransaction).getFrom();
                System.out.println("address " + from);
            } catch (SignatureException e) {
                e.printStackTrace();
            }
        }
        System.out.println("解密 end " + System.currentTimeMillis());
    }


    public static void parseInput() {
        String inputData = "0x6060604052341561000f57600080fd5b6b033b2e3c9fd0803ce80000006000818155600160a060020a03331681526001602052604090819020919091558051908101604052600b81527f574953444f4d546f6b656e000000000000000000000000000000000000000000602082015260039080516100819291602001906100d4565b5060408051908101604052600681527f574953444f4d0000000000000000000000000000000000000000000000000000602082015260049080516100c99291602001906100d4565b50601260055561016f565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061011557805160ff1916838001178555610142565b82800160010185558215610142579182015b82811115610142578251825591602001919060010190610127565b5061014e929150610152565b5090565b61016c91905b8082111561014e5760008155600101610158565b90565b6106ce8061017e6000396000f3006060604052600436106100985763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde03811461009d578063095ea7b31461012757806318160ddd1461015d57806323b872dd14610182578063313ce567146101aa57806370a08231146101bd57806395d89b41146101dc578063a9059cbb146101ef578063dd62ed3e14610211575b600080fd5b34156100a857600080fd5b6100b0610236565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156100ec5780820151838201526020016100d4565b50505050905090810190601f1680156101195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013257600080fd5b610149600160a060020a03600435166024356102d4565b604051901515815260200160405180910390f35b341561016857600080fd5b610170610340565b60405190815260200160405180910390f35b341561018d57600080fd5b610149600160a060020a0360043581169060243516604435610346565b34156101b557600080fd5b6101706104c8565b34156101c857600080fd5b610170600160a060020a03600435166104ce565b34156101e757600080fd5b6100b06104e9565b34156101fa57600080fd5b610149600160a060020a0360043516602435610554565b341561021c57600080fd5b610170600160a060020a036004358116906024351661064f565b60038054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102cc5780601f106102a1576101008083540402835291602001916102cc565b820191906000526020600020905b8154815290600101906020018083116102af57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294909152808220859055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a350600192915050565b60005481565b6000600160a060020a038316151561035d57600080fd5b600160a060020a03841660009081526001602052604090205482111561038257600080fd5b600160a060020a03808516600090815260026020908152604080832033909416835292905220548211156103b557600080fd5b600160a060020a0384166000908152600160205260409020546103de908363ffffffff61067a16565b600160a060020a038086166000908152600160205260408082209390935590851681522054610413908363ffffffff61068c16565b600160a060020a0380851660009081526001602090815260408083209490945587831682526002815283822033909316825291909152205461045b908363ffffffff61067a16565b600160a060020a03808616600081815260026020908152604080832033861684529091529081902093909355908516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060019392505050565b60055481565b600160a060020a031660009081526001602052604090205490565b60048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102cc5780601f106102a1576101008083540402835291602001916102cc565b6000600160a060020a038316151561056b57600080fd5b600160a060020a03331660009081526001602052604090205482111561059057600080fd5b600160a060020a0333166000908152600160205260409020546105b9908363ffffffff61067a16565b600160a060020a0333811660009081526001602052604080822093909355908516815220546105ee908363ffffffff61068c16565b600160a060020a0380851660008181526001602052604090819020939093559133909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600192915050565b600160a060020a03918216600090815260026020908152604080832093909416825291909152205490565b60008282111561068657fe5b50900390565b60008282018381101561069b57fe5b93925050505600a165627a7a72305820f53261ac8e62c8a145d59b673b64a48501bc3d0b6cfdb52556dd3d6d86994cb90029";
        inputData = "0x6060604052341561000f57600080fd5b6102458061001e6000396000f3006060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318160ddd811461005b57806370a0823114610080578063a9059cbb1461009f575b600080fd5b341561006657600080fd5b61006e6100d5565b60405190815260200160405180910390f35b341561008b57600080fd5b61006e600160a060020a03600435166100db565b34156100aa57600080fd5b6100c1600160a060020a03600435166024356100f6565b604051901515815260200160405180910390f35b60005481565b600160a060020a031660009081526001602052604090205490565b6000600160a060020a038316151561010d57600080fd5b600160a060020a03331660009081526001602052604090205482111561013257600080fd5b600160a060020a03331660009081526001602052604090205461015b908363ffffffff6101f116565b600160a060020a033381166000908152600160205260408082209390935590851681522054610190908363ffffffff61020316565b600160a060020a0380851660008181526001602052604090819020939093559133909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600192915050565b6000828211156101fd57fe5b50900390565b60008282018381101561021257fe5b93925050505600a165627a7a723058204ebc2682701d501c249fc46963dab35c5bc06e94d82dad680d3ed62f120e39850029";

        inputData = "0x608060405234801561001057600080fd5b506040516104793803806104798339818101604052606081101561003357600080fd5b810190808051604051939291908464010000000082111561005357600080fd5b90830190602082018581111561006857600080fd5b825164010000000081118282018810171561008257600080fd5b82525081516020918201929091019080838360005b838110156100af578181015183820152602001610097565b50505050905090810190601f1680156100dc5780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156100ff57600080fd5b90830190602082018581111561011457600080fd5b825164010000000081118282018810171561012e57600080fd5b82525081516020918201929091019080838360005b8381101561015b578181015183820152602001610143565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b5060405260209081015185519093506101a792506000918601906101c7565b5081516101bb9060019060208501906101c7565b50600255506102629050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061020857805160ff1916838001178555610235565b82800160010185558215610235579182015b8281111561023557825182559160200191906001019061021a565b50610241929150610245565b5090565b61025f91905b80821115610241576000815560010161024b565b90565b610208806102716000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806306fdde0314610046578063313ce567146100c357806395d89b41146100dd575b600080fd5b61004e6100e5565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610088578181015183820152602001610070565b50505050905090810190601f1680156100b55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100cb610173565b60408051918252519081900360200190f35b61004e610179565b6000805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561016b5780601f106101405761010080835404028352916020019161016b565b820191906000526020600020905b81548152906001019060200180831161014e57829003601f168201915b505050505081565b60025481565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561016b5780601f106101405761010080835404028352916020019161016b56fea265627a7a72315820df8b3d26ca94f83812f44fcbf740c2f17e945ef6f685619db349e36c5443a73764736f6c634300050b0032000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000457494c4c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035756540000000000000000000000000000000000000000000000000000000000";
        String method = inputData.substring(0, 10);
        String to = inputData.substring(10, 74);
        String value = inputData.substring(74);
        Method refMethod = null;
        try {
            refMethod = TypeDecoder.class.getDeclaredMethod("decode", String.class, int.class, Class.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        refMethod.setAccessible(true);
        Address address = null;
        try {
            address = (Address) refMethod.invoke(null, to, 0, Address.class);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        Uint256 amount = null;
        try {
            amount = (Uint256) refMethod.invoke(null, value, 0, Uint256.class);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println("method=" + method + "\nto=" + to + "\nvalue=" + value + "\naddress=" + address.getValue() + "\namount=" + amount.getValue());
    }

    public static void decodeInput() {
        try {
            String inputData = "0x6060604052341561000f57600080fd5b6102458061001e6000396000f3006060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318160ddd811461005b57806370a0823114610080578063a9059cbb1461009f575b600080fd5b341561006657600080fd5b61006e6100d5565b60405190815260200160405180910390f35b341561008b57600080fd5b61006e600160a060020a03600435166100db565b34156100aa57600080fd5b6100c1600160a060020a03600435166024356100f6565b604051901515815260200160405180910390f35b60005481565b600160a060020a031660009081526001602052604090205490565b6000600160a060020a038316151561010d57600080fd5b600160a060020a03331660009081526001602052604090205482111561013257600080fd5b600160a060020a03331660009081526001602052604090205461015b908363ffffffff6101f116565b600160a060020a033381166000908152600160205260408082209390935590851681522054610190908363ffffffff61020316565b600160a060020a0380851660008181526001602052604090819020939093559133909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600192915050565b6000828211156101fd57fe5b50900390565b60008282018381101561021257fe5b93925050505600a165627a7a723058204ebc2682701d501c249fc46963dab35c5bc06e94d82dad680d3ed62f120e39850029";
            String method = inputData.substring(0, 10);
            System.out.println("method ===" + method);
            System.out.println("method in Raw === " + ABIHexUtil.Hex32ToString(method, 3));
            String to = inputData.substring(10, 74);
            String value = inputData.substring(74);
            Method refMethod = TypeDecoder.class.getDeclaredMethod("decode", String.class, int.class, Class.class);
            refMethod.setAccessible(true);
            Address address = (Address) refMethod.invoke(null, to, 0, Address.class);
            System.out.println("address ===" + address.toString());
            Uint256 amount = (Uint256) refMethod.invoke(null, value, 0, Uint256.class);
            System.out.println("amount ===" + amount.getValue());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static void testTopic() {
	/*	String rawInput = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
        Type type = (Type) FunctionReturnDecoder.decode(rawInput, new TypeReference<Type>(){});
        System.out.println("type ==="+type.getValue());*/
    }

}
